// Copyright (c) 2010 Manuel Peinado Gallego <manuel.peinado@gmail.com>
// Distributed under the MIT license

#include "stdafx.h"
#include "WorldBuilder.h"
#include "PrimitiveFactory.h"
#include "Mesh.h"


void PrimitiveFactory::write(std::wostream& os, const Primitive& prim)
{
    // Write shape type
    PrimitiveType type = primitiveToType(prim);
    ASSERT(type != PrimitiveTypes::Unknown); // Should probably be an exception
    os << (int)type << "\n"; 
    
    prim.write(os);
}

ref<Primitive> PrimitiveFactory::read(std::wistream & is)
{
    // Read shape type
    int aux;
    is >> aux;
    PrimitiveType type = (PrimitiveType)aux; 
    ref<Primitive> shape  = primitiveFromType(type);
    ASSERT(shape != NULL); // Should probably be an exception
    shape->read(is);
    return shape;
}

// ************************************************************************


ref<Primitive> PrimitiveFactory::primitiveFromType(PrimitiveType type)
{
    switch(type)
    {
    case PrimitiveTypes::Sphere:
        return ref<Primitive>(new SphereShape);
    case PrimitiveTypes::Cube:
        return ref<Primitive>(new Cube);
    case PrimitiveTypes::Cylinder:
        return ref<Primitive>(new CylinderShape);
    default:
        return ref<Primitive>();
    }
}

PrimitiveType PrimitiveFactory::primitiveToType(const Primitive& shape)
{
    if(dynamic_cast<const SphereShape*>(&shape))
    {
        return PrimitiveTypes::Sphere;
    }
    if(dynamic_cast<const Cube*>(&shape))
    {
        return PrimitiveTypes::Cube;
    }
    if(dynamic_cast<const CylinderShape*>(&shape))
    {
        return PrimitiveTypes::Cylinder;
    }
    return PrimitiveTypes::Unknown;
}    

// ************************************************************************

ref<Primitive> PrimitiveFactory::primitiveFromName(const std::string& name)
{
    return primitiveFromType(nameToType(name));
}

std::string PrimitiveFactory::nameFromPrimitive(const Primitive& shape)
{
    return typeToName(primitiveToType(shape));
}

// ************************************************************************

PrimitiveType PrimitiveFactory::nameToType(const std::string& name)
{
    if(name == "Cylinder")
    {
        return PrimitiveTypes::Cylinder;
    }
    if(name  == "Sphere")
    {
        return PrimitiveTypes::Sphere;
    }
    if(name  == "Cube")
    {
        return PrimitiveTypes::Cube;
    }
    return PrimitiveTypes::Unknown;
}

std::string PrimitiveFactory::typeToName(PrimitiveType type)
{
    switch(type)
    {
    case PrimitiveTypes::Sphere:
        return "Sphere";
    case PrimitiveTypes::Cube:
        return "Cube";
    case PrimitiveTypes::Cylinder:
        return "Cylinder";
    default:
        return "Unknown";
    }
}
